

#ifndef MEMORY_UTIL_H_INCLUDED
#define MEMORY_UTIL_H_INCLUDED

#include <stdbool.h>
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#include <ebex_mempool.h>



#ifdef MEMORY_ALLOC_DEBUG
#	define	MALLOC_CHECK_	2
#endif


#define e_malloc(_size)		e_malloc_safe((_size),			\
				__func__, __FILE__, __LINE__)
#define e_memalign(_size)	e_memalign_safe((_size),		\
				__func__, __FILE__, __LINE__)
#define e_calloc(_num,_size)		e_calloc_safe((_num),(_size),			\
				__func__, __FILE__, __LINE__)
#define e_realloc(_oldptr,_size)		e_realloc_safe((_oldptr),(_size),			\
				__func__, __FILE__, __LINE__)
#define e_rememalign(_oldptr,_size)	e_rememalign_safe((_oldptr),(_size),			\
				__func__, __FILE__, __LINE__)
#define e_strndup(_str, _len)		e_strndup_safe((_str), (_len),		\
				__func__, __FILE__, __LINE__)
#define e_strdup(_str)		e_strdup_safe((_str),			\
				__func__, __FILE__, __LINE__)
#define e_free(_ptr)		e_free_safe((_ptr),			\
				__func__, __FILE__, __LINE__, true)
#define e_free_quiet(_ptr)		e_free_safe((_ptr),			\
				__func__, __FILE__, __LINE__, false)



void *e_malloc_safe(size_t, const char*, const char*, const int);
void *e_memalign_safe(size_t, const char*, const char*, const int);
void *e_calloc_safe(size_t, size_t, const char*, const char*, const int);
void *e_realloc_safe(void*, size_t, const char*, const char*, const int);
void *e_rememalign_safe(void*, size_t, const char*, const char*, const int);
char *e_strdup_safe(const char*, const char*, const char*, const int);
char *e_strndup_safe(const char*, size_t, const char*, const char*, const int);
void e_free_safe(void *ptr, const char *funcname, const char *filename, const int linenum, const bool m_warn);
void *e_memset(void *m_dest, register int_fast8_t m_char, register size_t m_len);

/** Zero an element */
#define EBEX_ZERO(x) e_memset((void*)&(x), 0, sizeof(x))
#define EBEX_ZERO_ELEM(x,num) e_memset((void*)(x), 0, (num)*sizeof(*(x)))

/** Zero dereferenced pointer */
#define EBEX_ZERO_P(x) do { if (x) e_memset((void*)(x), 0, sizeof(*(x))); } while(0)

#define EBEX_SWAP(x, y)	do { typeof(x) t; t = x; x = y; y = t; } while(0)

/**
 * Allocates a temporary, formated string on the stack.  This memory will be automatically freed
 * when the function exits, so do not call free or any variant on the pointer
 */
#define ebex_tmp_sprintf(ptr, format, ...) 					\
	do{														\
		int bytes;											\
															\
		bytes = snprintf(NULL, 0, format, ##__VA_ARGS__)+1;	\
															\
		if (bytes > 4000 / (int)sizeof(char)) 				\
		{													\
			fputs("Out of stack space", stderr);			\
			ptr=NULL;										\
		}													\
		else												\
		{													\
			ptr = alloca(bytes);							\
			snprintf(ptr, bytes, format, ##__VA_ARGS__);	\
		}													\
	}while(0)
#endif

